package controllers

import (
	"beego/comm/db"
	"beego/comm/entity"
	"beego/comm/requests"
	"beego/comm/source"
	"beego/comm/str"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"sync"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

type QueryFoodController struct {
	beego.Controller
}

var (
	lockQueryFoodRecord sync.Mutex
)

func save_data_to_temp_table(resp_data_map map[string]interface{}) int {
	o := orm.NewOrm()
	var food_record_items = map[string]interface{}{
		"sql": make([]string, 0),
		"len": 0,
	}
	hits_outside, _ := resp_data_map["hits"].(map[string]interface{})
	hits := int(hits_outside["total"].(float64))
	hits_inside, _ := hits_outside["hits"].([]interface{})
	for _, food_record := range hits_inside {
		_food_record := food_record.(map[string]interface{})
		_source := _food_record["_source"].(map[string]interface{})
		var food_item = map[string]interface{}{
			"id":               _food_record["_id"].(string),
			"record_date":      _source["date"],
			"user_name":        _source["username"],
			"meal_type":        _source["type"],
			"food":             _source["food"],
			"last_modify_time": _source["last_modify_time"],
		}
		food_record_items = str.GenInsertSql(food_record_items, food_item, "food_record_temp")
	}
	data_sql, _ := food_record_items["sql"].([]string)
	for _, food_item_v := range data_sql {
		beego.Info(food_item_v)
		exe_result, err := o.Raw(food_item_v).Exec()
		beego.Info(fmt.Sprintf("insert执行结果: %s", exe_result))
		beego.Info(fmt.Sprintf("执行状态: %s", err))
	}
	return hits
}

func query_food_record_temp_table_count(userName string) int {
	o := orm.NewOrm()
	var maps []orm.Params
	o.Raw(`select count(1) as count from food_record_temp where user_name = ?`).
		SetArgs(userName).Values(&maps)
	count, _ := strconv.ParseInt(maps[0]["count"].(string), 10, 64)
	return int(count)
}

func (c *QueryFoodController) QueryFood() {
	defer func() {
		err := recover()
		if nil != err {
			beego.Info("出现异常: ", err)
			c.Data["json"] = map[string]interface{}{
				"status":    false,
				"errorInfo": err,
			}
			c.ServeJSON()
			return
		}
	}()
	var food_record entity.FoodRecordQuery
	json.Unmarshal(c.Ctx.Input.RequestBody, &food_record)
	user_name := food_record.UserName
	user_loginID := food_record.LoginID
	beego.Info("登录信息: ", user_name, user_loginID)
	loginID, err := db.RedisGet("login-" + user_name)
	beego.Info("ES登录信息: ", loginID, err)
	if nil != err {
		panic(fmt.Sprintf("%s", err.Error()))
	}
	if "" == loginID || loginID != user_loginID {
		panic("请先登录")
	}
	var must_query []interface{}
	must_query = append(must_query, map[string]map[string]string{
		"match": {
			"username": user_name,
		},
	})
	food_type := strings.Trim(food_record.Type, " ")
	beego.Info("food_type: ", food_type)
	if "" != food_type {
		must_query = append(must_query, map[string]map[string]string{
			"match": {
				"type": food_type,
			},
		})
	}
	food := strings.Trim(food_record.Food, " ")
	beego.Info("food: ", food)
	if "" != food {
		must_query = append(must_query, map[string]map[string]interface{}{
			"nested": {
				"path": "food",
				"query": map[string]map[string]string{
					"match": {
						"food.food": food,
					},
				},
			},
		})
	}
	date_range := food_record.Date
	beego.Info("date_range: ", date_range)
	date_low := strings.Trim(date_range[0], " ")
	if "" != date_low {
		must_query = append(must_query, map[string]map[string]map[string]string{
			"range": {
				"date": {
					"gte":    date_low,
					"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis",
				},
			},
		})
	}
	date_high := strings.Trim(date_range[1], " ")
	if "" != date_low {
		must_query = append(must_query, map[string]map[string]map[string]string{
			"range": {
				"date": {
					"lte":    date_high,
					"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis",
				},
			},
		})
	}
	var sort_query []map[string]map[string]string
	sort_query = append(sort_query, map[string]map[string]string{
		"date": {
			"order": "desc",
		},
	})
	beego.Info("food_record.Size: ", food_record.Size)
	var query = map[string]interface{}{
		"query": map[string]interface{}{
			"bool": map[string]interface{}{
				"must": must_query,
			},
		},
		"size": food_record.Size,
		"sort": sort_query,
	}
	es_info := source.Src.GetEsInfo()
	beego.Info(es_info)
	var es_auth = map[string]string{
		"username": es_info["usr"],
		"password": es_info["pwd"],
	}
	o := orm.NewOrm()
	var maps []orm.Params
	beego.Info("food_record.From： ", food_record.From)
	var hits int = -1
	if 0 == food_record.From {
		beego.Info("查询ES")
		lockQueryFoodRecord.Lock()
		beego.Info("删除 food_record_temp 表数据")
		sql := "delete from food_record_temp where user_name = '" + food_record.UserName + "'"
		beego.Info(sql)
		exe_result, err := o.Raw(sql).Exec()
		beego.Info(fmt.Sprintf("delete执行结果: %s", exe_result))
		beego.Info(fmt.Sprintf("执行状态: %s", err))
		beego.Info("Restful查询ES")
		resp_data := requests.Post(
			source.Src.GetEsUrl()+"/food_record_index/food_records/_search",
			query, map[string]interface{}{"auth": es_auth})
		resp_data_map := make(map[string]interface{})
		json.Unmarshal([]byte(resp_data), &resp_data_map)
		beego.Info("保存数据到 food_record_temp")
		hits = save_data_to_temp_table(resp_data_map)
		lockQueryFoodRecord.Unlock()
	}
	count := query_food_record_temp_table_count(food_record.UserName)
	beego.Info("count: ", count)
	beego.Info("查询 food_record_temp")
	o.Raw(`select * from food_record_temp where user_name = ? order by record_date desc limit ?, ?`).
		SetArgs(food_record.UserName, food_record.From, food_record.Page).Values(&maps)
	beego.Info("查询结果条数 len(maps): ", len(maps))
	c.Data["json"] = map[string]interface{}{
		"status":    true,
		"hits":      hits,
		"count":     count,
		"data":      maps,
		"errorInfo": "",
	}
	c.ServeJSON()
}
